package fei.typhoon.engine.graphics;

import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PaintFlagsDrawFilter;
import android.graphics.Rect;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import fei.typhoon.engine.android.FeiScene;
import fei.typhoon.engine.android.FeiScreen;
import fei.typhoon.engine.utils.FeiArrayList;
import fei.typhoon.engine.utils.IFeiView;
import fei.typhoon.engine.utils.ITouchListener;

public class FeiSurface extends SurfaceView {
	// 在构造函数中初始化
	private SurfaceHolder surfaceHolder = null;
	/** 画图线程 */
	// 在surfaceCreated中初始化并启动，在surfaceDestroyed中中断并销毁
	private Thread drawThread = null;
	/** 画图频率控制锁 */
	// 在surfaceCreated中初始化
	private Object fpsLock = null;
	/** 画图工作标志 */
	// 在surfaceCreated中初始化
	private boolean working = true;
	/** activity */
	private FeiScreen screen = null;
	/** scene场景管理器 */
	private SceneManager sceneManager = null;
	/** 是否在运行中 */
	private boolean running = true;

	public FeiSurface(FeiScreen screen) {
		super(screen);
		this.screen = screen;
		surfaceHolder = getHolder();
		surfaceHolder.addCallback(new HolderCallback());
		surfaceHolder.setKeepScreenOn(true);
		sceneManager = new SceneManager();
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		boolean processed = false;
		if (event.getAction() == MotionEvent.ACTION_DOWN) {
			processed = sceneManager.touchDown(event.getX(), event.getY());
		} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
			processed = sceneManager.touchMove(event.getX(), event.getY());
		} else if (event.getAction() == MotionEvent.ACTION_UP) {
			processed = sceneManager.touchUp(event.getX(), event.getY());
		}
		return processed;
	}

	private void startSurface() {
		setWorking(true);
		fpsLock = new Object();
		drawThread = new Thread(new WorkRun(), "FEI_DRAW_THREAD");
		drawThread.setPriority(Thread.MAX_PRIORITY);
		drawThread.start();
	}

	private void stopSurface() {
		setWorking(false);
		if (drawThread != null) {
			try {
				drawThread.interrupt();
				drawThread = null;
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	private void drawScreen(Canvas canvas) {
		sceneManager.draw(canvas);
	}

	private void unlockCanvas(Canvas canvas) {
		try {
			if (canvas != null) {
				surfaceHolder.unlockCanvasAndPost(canvas);
			}
		} catch (Exception e) {
		}
	}

	public void addScene(FeiScene scene) {
		sceneManager.addScene(scene);

	}

	public void removeScene(FeiScene scene) {
		sceneManager.removeScene(scene);
	}

	public void setScene(FeiScene scene) {
		sceneManager.setScene(scene);
	}

	public void clearScene() {
		sceneManager.clearScene();
	}

	public void pause() {
		sceneManager.pause();
	}

	public void resume() {
		sceneManager.resume();
	}

	public void destroy() {
		sceneManager.destroy();
	}

	public boolean isWorking() {
		synchronized (fpsLock) {
			return working;
		}
	}

	public void setWorking(boolean working) {
		synchronized (fpsLock) {
			this.working = working;
		}
	}

	public boolean isRunning() {
		synchronized (fpsLock) {
			return running;
		}
	}

	public void setRunning(boolean running) {
		synchronized (fpsLock) {
			this.running = running;
		}
	}

	private class WorkRun implements Runnable {
		@Override
		public void run() {
			Canvas canvas = null;
			Rect rect = new Rect(0, 0, screen.getScreenWidth(), screen
					.getScreenHeight());
			while (isWorking()) {
				try {
					// 得到一个canvas实例
					canvas = surfaceHolder.lockCanvas(rect);
					// 刷屏
					canvas.drawARGB(255, 225, 228, 235);
					canvas.setDrawFilter(new PaintFlagsDrawFilter(0,
							Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG));
					// 绘制组件
					drawScreen(canvas);
					// 将画好的画布提交
					surfaceHolder.unlockCanvasAndPost(canvas);
					// 控制画图频率
					if (isRunning()) {
						synchronized (fpsLock) {
							fpsLock.wait(3);
						}
					} else {
						synchronized (fpsLock) {
							fpsLock.wait();
						}
					}
				} catch (InterruptedException e) {
					// 解锁画布
					unlockCanvas(canvas);
					setWorking(false);
					// 打印异常
					e.printStackTrace();
					break;
				} catch (Exception e) {
					// 解锁画布
					unlockCanvas(canvas);
					// 打印异常
					// e.printStackTrace();
				}
			}
		}

	}

	private class HolderCallback implements SurfaceHolder.Callback {

		@Override
		public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2,
				int arg3) {
		}

		@Override
		public void surfaceCreated(SurfaceHolder arg0) {
			startSurface();
		}

		@Override
		public void surfaceDestroyed(SurfaceHolder arg0) {
			stopSurface();
		}

	}

	private class SceneManager implements IFeiView, ITouchListener {
		/** 子view合集 */
		private FeiArrayList<FeiScene> scenes = null;
		private FeiArrayList<FeiScene> hides = null;
		private FeiScene current = null;
		private FeiScene touchScene = null;

		SceneManager() {
			scenes = new FeiArrayList<FeiScene>();
			hides = new FeiArrayList<FeiScene>();
		}

		@Override
		public void draw(Canvas canvas) {
			if (current != null) {
				current.draw(canvas);
			}
		}

		@Override
		public boolean touchDown(float x, float y) {
			boolean processed = false;
			touchScene = null;
			if (current != null) {
				processed = current.touchDown(x, y);
				if (processed) {
					touchScene = current;
				}
			}
			return processed;
		}

		@Override
		public boolean touchMove(float x, float y) {
			if (touchScene != null) {
				return touchScene.touchMove(x, y);
			}
			return false;
		}

		@Override
		public boolean touchUp(float x, float y) {
			if (touchScene != null) {
				return touchScene.touchUp(x, y);
			}
			return false;
		}

		void addScene(FeiScene scene) {
			if (!scenes.contains(scene)) {
				scenes.add(scene);
			}
		}

		void removeScene(FeiScene scene) {
			scenes.remove(scene);
			hides.remove(scene);
		}

		void setScene(FeiScene scene) {
			if (!scenes.contains(scene)) {
				addScene(scene);
			}
			if (hides.contains(scene)) {
				scene.resume();
				hides.remove(scene);
			}
			if (current != null && current != scene) {
				current.pause();
				hides.add(current);
			}
			current = scene;
		}

		void clearScene() {
			scenes.clear();
			hides.clear();
			current = null;
		}

		@Override
		public void destroy() {
			scenes.resetNext();
			while (scenes.hasNext()) {
				FeiScene scene = scenes.getNext();
				if (scene != null) {
					scene.destroy();
				}
			}
			clearScene();
			scenes = null;
			hides = null;
		}

		@Override
		public void pause() {
			if (current != null) {
				current.pause();
			}
		}

		@Override
		public void resume() {
			if (current != null) {
				current.resume();
			}
		}
	}

}
